﻿using System.Collections.Generic;

namespace InDepth2Demo.Chapter3
{
    // 协变_逆变_关键字
    internal class Out_In_Keywords
    {
        public static void Out()
        {
            List<object> listobject = new List<object>();
            List<string> liststrs = new List<string>();

            // AddRange(IEnumerable<T> collection)
            // public interface IEnumerable<out T> : IEnumerable
            // 即 泛型类型参数T 支持协变性
            listobject.AddRange(liststrs);

            // liststrs.AddRange(listobject); // 出错
        }

        public static void In()
        {
            List<string> liststrs = new List<string>();
            List<object> listobject = new List<object>();

            // IComparer<object> 这个接口的源码： public interface IComparer<in T>
            IComparer<object> objComparer = new TestComparer();
            IComparer<string> objComparer2 = new TestComparer();

            // public void Sort(IComparer<T> comparer)
            // public interface IComparer<in T>
            //  即 泛型类型参数T 支持逆变性
            liststrs.Sort(objComparer);

            // listobject.Sort(objComparer2);    // 出错
        }

        // 如果两个类型T和U之间存在一种安全的隐式转换，那么对应的数组类型 T[] 和 U[] 之间是否也存在这种转换呢？ 
        // 这种将原本类型上存在的类型转换映射到他们的数组类型的能力，这种能力就称为 "可变性（Variance）"。
        // 比如，String 类型继承自 Object 类型，所以任何 String 的引用都可以安全地转换为 Object 引用。
        // 我们发现 String[] 数组类型的引用也继承了这种转换能力，它可以转换成 Object[] 数组类型的引用，数组这种与原始类型转换方向相同的可变性就称作协变（covariant）。
        public static void Covariant()
        {
            string[] strs = new string[2];
            object[] objs = strs;       // 协变
        }

        public static void Test()
        {
            List<string> strings = new List<string>();
            //List<object> objs = strings;    //出错
        }
    }

    class TestComparer : IComparer<object>
    {
        public int Compare(object obj1, object obj2)
        {
            return obj1.ToString().CompareTo(obj2.ToString());
        }
    }
}
